//
//  RangeReplaceableCollection_Extensions.swift
//
//  Copyright © 2018 BitcoinKit developers
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//
import Foundation

extension RangeReplaceableCollection where Self: MutableCollection {

	/// Equivalence to Python's operator on lists: `[:n]`, e.g. `x = [1, 2, 3, 4, 5]; x[:3] // equals: [1, 2, 3]`
	func prefix(maxCount: Int) -> Self {
		return Self(self.prefix(maxCount))
	}

	/// Equivalent to Python's `[-n]`, e.g.`"Hello"[-3] // equals: "llo"`
	func suffix(maxCount: Int) -> Self {
		return Self(self.suffix(maxCount))
	}

	/// Equivalence to Python's operator on string: `[:-n]`, e.g.`"Hello"[:-3] // equals: "He"`
	func prefix(subtractFromCount n: Int) -> Self {
		let specifiedCount = count - n
		guard specifiedCount > 0 else { return Self() }
		return prefix(maxCount: specifiedCount)
	}

	func splitIntoChunks(ofSize maxLength: Int) -> [Self] {
		precondition(maxLength > 0, "groups must be greater than zero")
		var start = startIndex
		return stride(from: 0, to: count, by: maxLength).map { _ in
			let end = index(start, offsetBy: maxLength, limitedBy: endIndex) ?? endIndex
			defer { start = end }
			return Self(self[start..<end])
		}
	}
}
